"""Test configuration and fixtures."""

import asyncio
import os
import tempfile
import shutil
from pathlib import Path
from typing import AsyncGenerator

import pytest
import pytest_asyncio
from fastapi.testclient import TestClient

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from main import create_app
from core.config import ConfigManager
from core.database import AsyncVectorDBManager
from core.embedding import EmbeddingService


@pytest.fixture(scope="session")
def event_loop():
    """Create an instance of the default event loop for the test session."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()


@pytest.fixture(scope="session")
def temp_dir():
    """Create a temporary directory for testing."""
    temp_path = tempfile.mkdtemp(prefix="vectordb_test_")
    yield temp_path
    # Cleanup
    shutil.rmtree(temp_path, ignore_errors=True)


@pytest.fixture(scope="session")
def test_config(temp_dir):
    """Create test configuration."""
    config_data = {
        "service": {
            "name": "vectordb-test",
            "version": "1.0.0",
            "host": "127.0.0.1",
            "port": 8001,
            "log_level": "DEBUG"
        },
        "database": {
            "uri": f"{temp_dir}/test_vectordb",
            "config_path": f"{temp_dir}/test_config.json",
            "max_connections": 5,
            "min_connections": 1
        },
        "embedding": {
            "provider": "test",
            "model": "test-model",
            "vector_dimension": 768,
            "providers": {
                "test": {
                    "base_url": "http://localhost:8000",
                    "models": ["test-model"]
                }
            }
        }
    }

    # Create config manager with test data
    config_manager = ConfigManager(f"{temp_dir}/test_config.yaml")
    config_manager.update_config(config_data)

    return config_manager


@pytest_asyncio.fixture(scope="session")
async def test_db_manager(temp_dir, test_config):
    """Create test database manager."""
    db_config = test_config.config.database

    db_manager = AsyncVectorDBManager(
        uri=db_config.uri,
        config_path=db_config.config_path,
        max_connections=db_config.max_connections,
        min_connections=db_config.min_connections
    )

    await db_manager.initialize()
    yield db_manager
    await db_manager.cleanup()


@pytest_asyncio.fixture(scope="session")
async def test_embedding_service(test_config):
    """Create test embedding service."""
    service = EmbeddingService(test_config.config.embedding.dict())
    yield service
    await service.close()


@pytest.fixture(scope="session")
def test_client(test_config):
    """Create test client."""
    # Set environment to use test config
    os.environ["VECTORDB_CONFIG_PATH"] = f"{test_config.config_path}"

    app = create_app()
    client = TestClient(app)
    yield client


@pytest_asyncio.fixture
async def sample_vectors():
    """Generate sample vectors for testing."""
    import numpy as np

    # Generate 10 sample vectors of 768 dimensions
    vectors = np.random.randn(10, 768).tolist()
    texts = [f"Sample text {i}" for i in range(10)]
    metadata = [{"id": i, "type": "test"} for i in range(10)]

    return vectors, texts, metadata


@pytest_asyncio.fixture
async def test_table(test_db_manager):
    """Create a test table."""
    table_name = "test_table"
    await test_db_manager.create_table(table_name, vector_dim=768)
    return table_name


@pytest.fixture
def mock_ollama_response():
    """Mock Ollama API response."""
    return {
        "embedding": [0.1] * 768,
        "model": "qwen3-embedding:0.6b",
        "done": True
    }


@pytest.fixture
def mock_ollama_models_response():
    """Mock Ollama models API response."""
    return {
        "models": [
            {"name": "qwen3-embedding:0.6b", "size": 123456789},
            {"name": "nomic-embed-text", "size": 987654321}
        ]
    }


# WebSocket test fixtures
@pytest_asyncio.fixture
async def websocket_client(test_client):
    """Create WebSocket test client."""
    with test_client.websocket_connect("/ws") as websocket:
        yield websocket


# Cleanup fixtures
@pytest_asyncio.fixture(autouse=True)
async def cleanup_test_data(test_db_manager):
    """Clean up test data after each test."""
    yield
    # Clean up test tables
    tables = await test_db_manager.list_tables()
    for table in tables:
        if table.startswith("test_"):
            try:
                await test_db_manager.create_table(table, overwrite=True)
            except Exception:
                pass  # Ignore cleanup errors